package com.dw.article.controller;


import cn.hutool.core.date.DateTime;
import cn.hutool.core.util.IdUtil;
import com.alibaba.nacos.shaded.com.google.common.collect.Lists;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.dw.article.mapper.ee.EeArticleInfoMapper;
import com.dw.article.service.ArticleInfoService;
import com.dw.article.service.ArticleMappingService;
import com.dw.article.service.ArticleUserService;
import com.dw.article.utils.LoginUtil;
import com.dw.common.entitys.BaseResponse;
import com.dw.common.enums.ErrorCode;
import com.dw.common.utils.ResultUtils;
import com.dw.model.article.dtos.article.AddArticleDTO;
import com.dw.model.article.dtos.article.QueryArticleDTO;
import com.dw.model.article.dtos.comment.QueryCommentDTO;
import com.dw.model.article.dtos.mapping.AddArticleMappingDTO;
import com.dw.model.article.dtos.user.AddArticleUserDTO;
import com.dw.model.article.entitys.ArticleInfo;
import com.dw.model.article.entitys.ArticleMapping;
import com.dw.model.article.entitys.CategoryInfo;
import com.dw.model.article.entitys.LabelInfo;
import com.dw.model.article.vos.article.GetCountVO;
import com.dw.model.article.vos.article.QueryByIdVO;
import com.dw.model.article.vos.article.QueryUserArticleVO;
import com.dw.model.article.vos.article.SearchArticleVO;
import com.dw.model.article.vos.comment.QueryCommentVO;
import lombok.extern.slf4j.Slf4j;
import org.dromara.easyes.core.conditions.select.LambdaEsQueryWrapper;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 文章信息表(ArticleInfo)表控制层
 *
 * @author makejava
 * @since 2024-10-05 18:29:36
 */
@Slf4j
@RestController
@RequestMapping("/article")
public class ArticleInfoController {

    @Resource
    private EeArticleInfoMapper eeArticleInfoMapper;

    @Resource
    private ArticleInfoService articleInfoService;

    @Resource
    private ArticleMappingService articleMappingService;

    @Resource
    private ArticleUserService articleUserService;

    @Resource
    private RedisTemplate redisTemplate;

    private final String ARTICLE_RANK_KEY = "article.rank";


    @GetMapping("/createIndex")
    public Boolean createIndex() {
        // 1.初始化-> 创建索引(相当于mysql中的表)
        return eeArticleInfoMapper.createIndex("article_info");
    }

    /**
     * 新增文章
     */
    @PostMapping("/add")
    public BaseResponse<Boolean> insert(@RequestBody @Valid AddArticleDTO addArticleDTO) {
        // 狗屎碧油鸡，ee的mapper层方法不能在mp的service层调用，调用后可以正常插入数据，但是查询查不到一点啊
        log.info("新增文章参数:{}", addArticleDTO);
        // 参数拷贝
        ArticleInfo articleInfo = new ArticleInfo();
        BeanUtils.copyProperties(addArticleDTO, articleInfo);
        // 设置创建时间
        DateTime currentTime = DateTime.now();
        articleInfo.setCreatedTime(currentTime);
        // 设置文章id
        long articleId = IdUtil.getSnowflake().nextId();
        articleInfo.setLeiId(articleId);
        // 设置创建人id
        String loginId = LoginUtil.getLoginId();
        articleInfo.setCreatedBy(Long.valueOf(loginId));
        // 将文章基本信息存入数据库
        ArticleInfo mpArticleInfo = new ArticleInfo();
        mpArticleInfo.setCreatedTime(DateTime.now());
        mpArticleInfo.setLeiId(articleId);
        mpArticleInfo.setCreatedBy(Long.valueOf(loginId));
        articleInfoService.save(mpArticleInfo);
        // 向文章映射表添加数据
        articleInfoService.addMapping(addArticleDTO,articleId);
        // ee新增文章
        Integer insert = eeArticleInfoMapper.insert(articleInfo);
        return ResultUtils.success(insert > 0);
    }

    /**
     * 条件分页查询文章
     */
    @PostMapping("/search")
    public BaseResponse<List<SearchArticleVO>> search(@RequestBody QueryArticleDTO queryArticleDTO) {
        try {
            if(log.isInfoEnabled()){
                log.info("ArticleInfoController search queryArticleDTO:{}", queryArticleDTO);
            }
            // 条件查询
            LambdaEsQueryWrapper<ArticleInfo> wrapper = new LambdaEsQueryWrapper<>();
            wrapper.like(ArticleInfo::getArticleTitle, queryArticleDTO.getInput())
                    .or().like(ArticleInfo::getArticleContent, queryArticleDTO.getInput())
                    .or().like(ArticleInfo::getNickname, queryArticleDTO.getInput())
                    .orderByDesc(ArticleInfo::getCreatedTime);
            List<ArticleInfo> articleInfos = eeArticleInfoMapper.selectList(wrapper);
            // 根据分类id过滤
            if (queryArticleDTO.getCategoryId() != null){
                List<Long> longs = articleMappingService.queryByCategoryId(queryArticleDTO.getCategoryId());
                // 如果当前分类没有文章，则返回空集合
                if (longs.isEmpty()) return ResultUtils.success(Lists.newArrayList());
                articleInfos = articleInfos.stream().filter(articleInfo -> longs.contains(articleInfo.getLeiId())).collect(Collectors.toList());
            }
            // 分页查询
            List<List<ArticleInfo>> partition = Lists.partition(articleInfos, queryArticleDTO.getPageSize());
            List<ArticleInfo> articleInfoList = partition.get(queryArticleDTO.getCurrent() - 1);
            // 如果是热门分类，按热度排序
            if (queryArticleDTO.getCategoryId() != null && queryArticleDTO.getCategoryId() == 1846528419689062400L){
                int start = (queryArticleDTO.getCurrent() - 1) * queryArticleDTO.getPageSize();
                int end = start + queryArticleDTO.getPageSize();
                Set<ZSetOperations.TypedTuple<Long>> set = redisTemplate.opsForZSet().reverseRangeWithScores(ARTICLE_RANK_KEY, start, end);
                if(CollectionUtils.isEmpty(set)){
                    return ResultUtils.success(Collections.emptyList());
                }
                articleInfoList = set.stream().map(rank -> {
                    ArticleInfo articleInfo = new ArticleInfo();
                    articleInfo.setArticleFire(rank.getScore().longValue());
                    articleInfo.setLeiId(rank.getValue());
                    return articleInfo;
                }).collect(Collectors.toList());
            }
            // 终极查询！！！
            List<SearchArticleVO> result = articleInfoService.queryArticleInfo(articleInfoList);
            return ResultUtils.success(result);
        } catch (Exception e){
            log.error("ArticleInfoController search error:{}",e.getMessage(),e);
            return ResultUtils.error(ErrorCode.SYSTEM_ERROR,"条件分页查询文章报错");
        }
    }

    /**
     * 根据分类id查询文章列表
     */
    @GetMapping("/queryByCategoryId")
    public List<ArticleInfo> queryByCategoryId(@RequestParam Long categoryId) {
        try {
            if(log.isInfoEnabled()){
                log.info("ArticleInfoController queryByCategoryId categoryId:{}:{}", categoryId);
            }
            // 获取该分类下的所有文章id
            List<Long> ids = articleMappingService.queryByCategoryId(categoryId);
            // 根据文章id列表查询所有文章
            List<ArticleInfo> articleInfos = articleInfoService.queryByIds(ids);
            return articleInfos;
        } catch (Exception e){
            log.error("ArticleInfoController queryByCategoryId error:{}",e.getMessage(),e);
            return new LinkedList<>();
        }
    }

    /**
     * 查询热门文章排行榜
     */
    @GetMapping("/queryHot")
    public BaseResponse<List<SearchArticleVO>> queryHotArticle() {
        try {
            if(log.isInfoEnabled()){
                log.info("ArticleInfoController queryHotArticle");
            }
            // 查询热度前10名的所有文章
            List<ArticleInfo> articleInfos = articleUserService.queryHotArticle();
            List<ArticleInfo> collect = articleInfos.stream().map(articleInfo -> {
                LambdaEsQueryWrapper<ArticleInfo> wrapper = new LambdaEsQueryWrapper<>();
                wrapper.eq(ArticleInfo::getLeiId, articleInfo.getLeiId());
                ArticleInfo eeArticleInfo = eeArticleInfoMapper.selectOne(wrapper);
                eeArticleInfo.setArticleFire(articleInfo.getArticleFire());
                return eeArticleInfo;
            }).collect(Collectors.toList());
            // 终极查询
            List<SearchArticleVO> result = articleInfoService.queryArticleInfo(collect);
            return ResultUtils.success(result);
        } catch (Exception e){
            log.error("ArticleInfoController queryHotArticle error:{}",e.getMessage(),e);
            return ResultUtils.error(ErrorCode.SYSTEM_ERROR,"查询热门文章排行榜报错");
        }
    }

    /**
     * 查询用户发布的所有帖子
     */
    @GetMapping("/queryUserArticle/{userId}")
    public BaseResponse<List<SearchArticleVO>> queryUserArticle(@PathVariable("userId") Long userId) {
        try {
            if(log.isInfoEnabled()){
                log.info("ArticleInfoController queryUserArticle userId:{}",userId);
            }
            // 条件查询
            LambdaEsQueryWrapper<ArticleInfo> wrapper = new LambdaEsQueryWrapper<>();
            wrapper.eq(ArticleInfo::getCreatedBy, userId);
            List<ArticleInfo> articleInfos = eeArticleInfoMapper.selectList(wrapper);
            // 终极查询
            List<SearchArticleVO> result = articleInfoService.queryArticleInfo(articleInfos);
            return ResultUtils.success(result);
        } catch (Exception e){
            log.error("ArticleInfoController queryUserArticle error:{}",e.getMessage(),e);
            return ResultUtils.error(ErrorCode.SYSTEM_ERROR,"查询用户发布的所有帖子报错");
        }
    }

    /**
     * 查询用户获赞数量
     */
    @GetMapping("/queryUserLike/{userId}")
    public BaseResponse<Integer> queryUserLike(@PathVariable("userId") Long userId) {
        try {
            if(log.isInfoEnabled()){
                log.info("ArticleInfoController queryUserLike userId:{}",userId);
            }
            // 条件查询
            LambdaEsQueryWrapper<ArticleInfo> wrapper = new LambdaEsQueryWrapper<>();
            wrapper.eq(ArticleInfo::getCreatedBy, userId);
            List<ArticleInfo> articleInfos = eeArticleInfoMapper.selectList(wrapper);
            // 终极查询
            List<SearchArticleVO> result = articleInfoService.queryArticleInfo(articleInfos);
            // 点赞数量
            int count = 0;
            for (SearchArticleVO searchArticleVO : result){
                count += searchArticleVO.getLikeCount();
            }
            return ResultUtils.success(count);
        } catch (Exception e){
            log.error("ArticleInfoController queryUserLike error:{}",e.getMessage(),e);
            return ResultUtils.error(ErrorCode.SYSTEM_ERROR,"查询用户获赞数量报错");
        }
    }

}

